//------------------------------------------------------------------------------
//	file dd.c
//
//	brief
//		data-display / data-dump (implementation file)
//
//	Description
//
//	$Id: dd.c 363 2015-03-06 19:10:49Z ac.verbeck@gmail.com $
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
//	The MIT License (MIT)
//
//	Copyright (c) 2014 A.C. Verbeck
//
//	Permission is hereby granted, free of charge, to any person obtaining a copy
//	of this software and associated documentation files (the "Software"), to deal
//	in the Software without restriction, including without limitation the rights
//	to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//	copies of the Software, and to permit persons to whom the Software is
//	furnished to do so, subject to the following conditions:
//
//	The above copyright notice and this permission notice shall be included in
//	all copies or substantial portions of the Software.

//	THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//	IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//	FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//	AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//	LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//	OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//	THE SOFTWARE.
//------------------------------------------------------------------------------
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>

#include "dd.h"

static uint8_t			addr;
static XFER_ADDR_E		addr_stat;
static I2C_INFO_BLK_T	i_blk;
static const uint32_t	i_blk_sz = sizeof(i_blk);

//------------------------------------------------------------------------------
// dd_init: dump data (data display) init
//
// Initializes the dd module
//
// Parameters: none
//
// Returns: none
//------------------------------------------------------------------------------
void dd_init(void)
{
	addr = 0;																	// set address to zero
	addr_stat = DD_ALL;															// enable all addresses
	memset(&i_blk, 0, i_blk_sz);												// clear the local block to zero
}

//------------------------------------------------------------------------------
// dd_init: dump data (data display) full-print
//
// Data display full print (headers, address tags, etc.)
//
// Parameters:
// uint8_t p*:	pointer to the data
// uint32_t sz:	size of the data to print
//
// Returns: none
//------------------------------------------------------------------------------
void dd_full(const uint8_t* p, uint32_t sz)
{
	uint32_t i;

	printf("      00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f");			// print the header
	for (i=0; i<sz; i++) {														// go through the buffer
		if ((i % 16) == 0)	printf("\n%04x: ", i);								// at 16 byte boundaries (including the first byte), print nl and byte offset
		printf("%02x ", *p++);													// print the byte
	}
	printf("\n");																// one last new line
}

//------------------------------------------------------------------------------
// dd_mini: dump data (data display) mini-print
//
// Mini print (just the data)
//
// Parameters:
// uint8_t p*:	pointer to the data
// uint32_t sz:	size of the data to print
//
// Returns: none
//------------------------------------------------------------------------------
void dd_mini(const uint8_t* p, uint32_t sz)
{
	uint32_t i;

	for (i=0; i<sz; i++) printf("%02x ", *p++);									// print the data
	printf("\n");																// one last new line
}

//------------------------------------------------------------------------------
// dd_i2c_get_block: get I2C information block
//
// Acquires a pointer to a local I2C information block
// Note that this function is easy to abuse.
//
// Parameters: none
//
// Returns:
// I2C info block pointer
//------------------------------------------------------------------------------
I2C_INFO_BLK_T*	dd_i2c_get_block(void)
{
	memset(&i_blk, 0, i_blk_sz);												// clear the block
	return &i_blk;																// send it on
}

//------------------------------------------------------------------------------
// dd_i2c_set_filter: print the information block
//
// Set a filter for dd_i2c_xfer_info()
//
// Parameters: none
// I2C info block pointer
//
// Returns: none
//------------------------------------------------------------------------------
void dd_i2c_set_filter(XFER_ADDR_E t, uint32_t a)
{
	switch(t) {																	// switch on the filter type
	case DD_ALL:																// allow all addresses
		addr_stat = DD_ALL;														// set status
		addr = 0;																// clear address
		break;																	// done
	case DD_NONE:																// mute all output
		addr_stat = DD_NONE;													// set status
		addr = 0;																// clear address
		break;																	// done
	case DD_ADDRESS:															// filter to specific address
		addr_stat = DD_ADDRESS;													// set status
		addr = a;																// set address
		break;																	// done
	}
}

//------------------------------------------------------------------------------
// dd_i2c_xfer_info: print the information block
//
// Dumps a block of data in a simple format
//
// Parameters:
// I2C_XFER_E		t:	transfer type
// I2C_INFO_BLK_T*	ib:	informatio block for printing
//
// Returns: none
//------------------------------------------------------------------------------
void dd_i2c_print(I2C_XFER_E t, I2C_INFO_BLK_T* ib)
{
	bool ret_stat = false;														// used to decide print status

	switch (addr_stat) {														// switch on address status
	case DD_ALL:																// print all addresses
		ret_stat = false;														// do not return
		break;
	case DD_NONE:																// print no addresses
		ret_stat = true;														// return
		break;
	case DD_ADDRESS:															// print specified address
		ret_stat = (ib->addr == addr) ? false : true;							// return if not specified address
		break;
	}
	if (ret_stat == true) return;												// return if filtered out...

	printf("Addr:%02x Stat:%d TX:%d RX:%d type:",								// print i2c transaction basics:
		ib->addr, ib->stat, ib->txCt, ib->rxCt);								// address, transaction status, tx/rx count

	switch (t) {																// print i2c transaction type
	case I2C_READ:			printf("read\n");		break;
	case I2C_WRITE:			printf("write\n");		break;
	case I2C_READ_ONLY:		printf("read only");	break;
	}

	if (ib->txCt > 0) dd_mini(ib->pTx, ib->txCt);								// print transmit buffer
	if (ib->rxCt > 0) dd_mini(ib->pRx, ib->rxCt);								// print receive buffer
	printf("\n");																// print a blank line
}

//
//	end dd.c
//
